<template>
  <a-table v-if="tableShow" class="draggTable" :columns="props.columns" :data-source="dataList" :pagination="false"
    :rowSelection="props.rowSelection" @expandedRowsChange="expandedTable" :expandedRowKeys="expandKeysList"
    :rowKey="rowKey">
    <template v-for="(value, key) in slots" v-slot:[key]="slotProps" :key="key">
      <slot :name="key" v-bind="slotProps"></slot>
    </template>
  </a-table>
</template>

<script lang="ts" setup>
import { ref, nextTick, reactive, computed, useSlots, onMounted, watch, onBeforeUnmount } from "vue";
import Sortable from "sortablejs";
import { SortableOptions } from 'sortablejs';
import { dragTreeProps } from "./tableConfig/props";

import { dataSourceType } from "../../type.d";
import { message } from "ant-design-vue";
//props
const props = defineProps(
  Object.assign({ ...dragTreeProps }, {
    ele: {
      type: String,
      default: ''
    },
    allOpenValue: {
      type: Boolean,
      default: false
    }
  })
);
//emit
const emit = defineEmits(["dragEnd"]);
//data
let tableShow = ref<Boolean>(false); // 表格显示隐藏，用于refresh数据用的

let dataList = ref<dataSourceType[]>([]); //表格数据源
let selectedRowKeys = ref<dataSourceType[]>([]); // 选中的列表id集合
let expandKeysList = ref<dataSourceType[]>([]); // 展开的列表id集合
let flatData = ref<dataSourceType[]>([]); // 拍平的数据
// let isOnce = true;
//computed
dataList = computed(() => {
  flatData.value = treeToTile(props.dataSource);
  return JSON.parse(JSON.stringify(props.dataSource));
});
// watch
// watch(() => props.dataSource, (newVal, oldVal) => {
//   if (newVal) { // 只上来监听一次
//     treeToTile(newVal).forEach((item: dataSourceType) => {
//       if (item.children instanceof Array && item.children.length) {
//         expandKeysList.value.push(item.id);
//       }
//     })
//   }
//   // isOnce = false;

// })
watch(() => props.allOpenValue, (newVal,oldVal) => {
  if(newVal == true) {
    treeToTile(props.dataSource).forEach((item: dataSourceType) => {
      if (item.children instanceof Array && item.children.length) {
        expandKeysList.value.push(item.id);
      }
    })
  }else {
  expandKeysList.value = []
  }
})
const rowConfig = computed(() => {
  return {
    selectedRowKeys: selectedRowKeys.value,
    onChange: tableChange,
  };
});
//mounted

//methods
const slots = useSlots();
const tableChange = (key: []) => {
  selectedRowKeys.value = key;
};
const expandedTable = (keys: []) => {
  if (tableShow.value) {
    expandKeysList.value = keys;
  }
  //refreshTable();
};
const refreshTable = () => {
  tableShow.value = false;
  nextTick(() => {
    tableShow.value = true;
    nextTick(() => {
      inintDrag();
    });
  });
};
const treeToTile = (treeData: dataSourceType[], childKey = "children") => {
  //用于拍平数据， 可考虑公用global.ts中使用
  const arr: dataSourceType[] = [];
  const expanded = (data: dataSourceType[]) => {
    if (data && data.length > 0) {
      data
        .filter((d) => d)
        .forEach((e) => {
          arr.push(e);
          expanded(e[childKey] || []);
        });
    }
  };
  expanded(treeData);
  return arr;
};
const inintDrag = () => {
  nextTick(() => {
    let sortDom = document.querySelector(`#${props.ele} .ant-table-tbody`);
    let dragged: dataSourceType[] = [];
    let related: dataSourceType[] = [];
    let IsCanDrag: boolean = true;
    let Oldindex: any = 0;

    Sortable.create(sortDom as HTMLElement, {
      disabled: false,
      //sort:true, // 给了就无法拖动
      //handle: ".ant-table-row",
      animation: 150,
      draggable: '.ant-table-row', // tr拖动
      dragClass: "dragClass",
      dataIdAttr: "chosenClass", //给停靠位置添加的class（可以给这个class定义样式
      ghostClass: "ghostClass",
      forceFallback: false,
      fallbackClass: "sortable-fallback",  // 当使用forceFallback的时候，被复制的dom的css类名
      onStart({ item }) {
        let targetRowKey = item.dataset.rowKey;
        let targetRowData =
          flatData.value.filter((item, index) => (targetRowKey == item.id))[0] || [];
        // flatData.value.forEach((item, index) => {

        // });
        let Parent: dataSourceType[] = flatData.value.filter(
          (item_flat) => targetRowData.parentId == item_flat.id
        );
        let sameLevel: (string | number)[] = [];
        if (Parent.length) {
          Parent[0].children.forEach((item: any, index: number) => {
            sameLevel.push(item.id);
            if (targetRowKey == item.id) {
              Oldindex = index
            }
          });
          if (targetRowKey) {
            expandKeysList.value = expandKeysList.value.filter(
              (item: any) => !sameLevel.includes(item)
            );
          }
        } else {
          dataList.value.forEach((item_data: any, index: number) => {
            if (targetRowKey == item_data.id) {
              Oldindex = index + 1;
            }
          })
          expandKeysList.value = [];
        }
      },
      onMove(evt) {
        dragged = flatData.value.filter(
          (item) => evt.dragged.dataset.rowKey == item.id
        );
        related = flatData.value.filter(
          (item) => evt.related.dataset.rowKey == item.id
        );
        if (dragged[0]?.parentId != related[0]?.parentId) {
          IsCanDrag = false;
          return false;
        } else if (dragged[0]?.isTop) {
          IsCanDrag = false;
          return false;
        } else {
          IsCanDrag = true;
        }

      },
      onEnd: ({ newIndex, item }: { newIndex: any; item: any }) => {
        if (flatData.value[newIndex]?.isTop) {
          IsCanDrag = false
        }
        if (!IsCanDrag) {
          refreshTable();
          message.warning("不可拖拽互换位置！！");
          return;
        }
        let Parent: dataSourceType[] = flatData.value.filter(
          (data) => dragged[0]?.parentId == data.id
        );
        let Targetindex: number = newIndex;// 拖拽的元素和第Targetindex个子元素将要互换位置
        Parent[0] && Parent[0].children && Parent[0].children.forEach((data: any, index: number) => {
          if (related[0].id == data.id) {
            Targetindex = index
          }
        });
        let targetRowKey = item.dataset.rowKey;// 拖拽的元素
        let targetArray = []; // 获取拖拽元素的真正层级，会找到最上层的
        let dataListItem: dataSourceType = {};
        let targetItem: dataSourceType = {};
        let currentRowKey = "";
        let currentArray = [];
        let isNext = false;
        let notBelong = false;
        if (targetRowKey || targetRowKey == 0) {
          targetArray = getTargeIndex(dataList.value, targetRowKey.toString());
        }
        if (newIndex - 1 > 0) {// newIndex是从1开始的
          // 要替换的是哪个tr
          currentRowKey = (
            document.querySelectorAll(".ant-table-row")[+newIndex - 1 - 1] as any
          ).dataset.rowKey;
          // 判断下一个tr是否存在，不存在就无法进行拖拽
          if (document.querySelectorAll(".ant-table-row")[+newIndex - 1 + 1]) {
            let raltedEleKey = flatData.value.filter(
              (item) =>
                (
                  document.querySelectorAll(".ant-table-row")[
                  +newIndex - 1 + 1
                  ] as any
                ).dataset.rowKey == item.id
            );
            if (raltedEleKey[0]?.parentId == dragged[0]?.parentId) {
              currentRowKey = (
                document.querySelectorAll(".ant-table-row")[+newIndex - 1 + 1] as any
              ).dataset.rowKey;
              isNext = true;
            }
          }
        }
        targetArray.forEach((item: string | number, index: number) => {
          item = +item;
          if (index < targetArray.length - 1) {
            if (!index) {
              targetItem = dataList.value[item];
            } else {
              targetItem = targetItem.children[item];
            }
          } else {
            if (!index) {
              // targetArray是[0,1,1]这样的嵌套，标明是第一层，第二层，第三层..
              targetItem = JSON.parse(JSON.stringify(dataList.value[item]));
              if (targetItem.children) {
                //查看第一层级的children是否看有目标替换的元素的key值
                notBelong = judgeBelong(currentRowKey, targetItem.children);
              }
              if (!notBelong) {
                // 如果第一层级的children里不包含，则直接把这个item删除
                dataList.value.splice(item, 1);
              }
            } else {
              let calcItem = JSON.parse(
                JSON.stringify(targetItem.children[item])
              );
              if (calcItem.children) {
                notBelong = judgeBelong(currentRowKey, calcItem.children);
              }
              if (!notBelong) {
                targetItem.children.splice(item, 1);
                targetItem = calcItem;
              }
            }
          }
        });
        if (!notBelong) {
          if (newIndex > 0) {
            if (currentRowKey) {
              currentArray = getTargeIndex(
                dataList.value,
                currentRowKey.toString()
              );
            }
            currentArray.forEach((item: string | number, index: number) => {
              item = +item;
              if (index < currentArray.length - 1) {
                if (!index) {
                  dataListItem = dataList.value[item];
                } else {
                  dataListItem = dataListItem.children[item];
                }
              } else {
                if (!index) {
                  if (!isNext) {
                    dataList.value.splice(item + 1, 0, targetItem);
                  } else {
                    dataList.value.splice(item, 0, targetItem);
                  }
                } else {
                  if (!isNext) {
                    dataListItem.children.splice(item + 1, 0, targetItem);
                  } else {
                    dataListItem.children.splice(item, 0, targetItem);
                  }
                }
              }
            });
          } else {
            dataList.value.unshift(targetItem);
          }
        }
        dataList.value = JSON.parse(JSON.stringify(dataList.value));
        refreshTable();
        console.log(Oldindex, Targetindex)
        emit('dragEnd', { id: dragged[0]?.id, toId: related[0]?.id, isBefore: Oldindex > Targetindex })
        // message.success("拖拽互换位置成功！！");
      },
    });
  })

};
const getTargeIndex: any = (
  list: dataSourceType[],
  id: string | number,
  arr = []
) => {
  return list.reduce((total: any, item, index) => {
    if (item.id.toString() === id) {
      return [...total, index];
    } else {
      if (item.children && item.children.length) {
        let childArr = getTargeIndex(item.children, id, [...arr, index]);
        if (childArr.length === [...arr, index].length) {
          childArr = total;
        }
        return childArr;
      } else {
        return total;
      }
    }
  }, arr);
};
const judgeBelong: any = (key: string | number, list = []) => {
  return list.find((item: dataSourceType) => {
    if (item.id.toString() === key) {
      return true;
    } else {
      if (item.children && item.children.length) {
        return judgeBelong(key, item.children);
      } else {
        return false;
      }
    }
  });
};
onMounted(() => {
  tableShow.value = true;
  nextTick(() => {
    inintDrag();
  });
})

</script>

<style lang="less">
.draggTable {
  height: calc(100% - 80px);
  overflow: hidden;

  .ant-table-row {
    cursor: move;
    // 禁止文字被鼠标选中 
    moz-user-select: -moz-none;
    -moz-user-select: none;
    -o-user-select: none;
    -khtml-user-select: none;
    -webkit-user-select: none;
    -ms-user-select: none;
    user-select: none;
  }

  .siteName {
    overflow: auto;
  }




}
</style>
